#include "MonteCarloIterator.h"

#include "../../math/Random.h"
#include "../../qt/Logger.h"

#include "Cell.h"
#include "World.h"

/*
	MonteCarloIterator
*/

/*	public	*/

MonteCarloIterator::MonteCarloIterator(World& world) :
	_world(world) {

	world._iterator = this;
//	Logger::debug(QString("=== MonteCarloIterator::MonteCarloIterator() _updatesCount = %1").arg(_updatesCount));
}

void MonteCarloIterator::startStep() {
	_updatesCount = _world._boundingBoxWidth * _world._boundingBoxHeight;
	_updatesLeft  = _updatesCount;
}

bool MonteCarloIterator::getTilePair(int* pxTile, int* pyTile, int* pxNeighbour, int* pyNeighbour) {
//	Logger::debug(">>> MonteCarloIterator::getTilePair()");
//	Logger::debug(QString(">>> MonteCarloIterator::getTilePair() _updatesCount = %1   _updatesLeft = %2").arg(_updatesCount).arg(_updatesLeft));

	/* random */
	Random random = Random::getInstance();

	int worldWidth  = _world._width;
	int worldHeight = _world._height;

	while(_updatesLeft != 0) {
//		Logger::debug(QString("\t_updatesLeft = %1").arg(_updatesLeft));

		--_updatesLeft;

		/* random tile */
		int xTile = _world._x1 - 1 + random.getInt(_world._boundingBoxWidth  + 2);
		int yTile = _world._y1 - 1 + random.getInt(_world._boundingBoxHeight + 2);

		/* random neighbour tile */
		int xNeighbour = xTile;
		int yNeighbour = yTile;
		/* 	select */
		int neighbourNumber = random.getInt(4);
		switch(neighbourNumber) {
		case 0:
			--yNeighbour;
			break;
		case 1:
			++xNeighbour;
			break;
		case 2:
			++yNeighbour;
			break;
		case 3:
			--xNeighbour;
			break;
		default:
			Logger::debug(QString("Rather messed up : random.getInt(4) => %1").arg(neighbourNumber));
			assert(false);
		}

		/* if on the grid border, ignore */
		if (xNeighbour <= 0
		|| xNeighbour >= worldWidth - 1
		|| yNeighbour <= 0
		|| yNeighbour >= worldHeight - 1) {
			continue;
		}

		/* tile id */
		CellId tileId = _world.grid(xTile, yTile);

		/* neighbour id */
		CellId neighbourId = _world.grid(xNeighbour, yNeighbour);

		/* tiles belong to different cells/substrate ? */
		if (tileId != neighbourId) {
			/* tile */
			*pxTile = xTile;
			*pyTile = yTile;
			/* neighbour */
			*pxNeighbour = xNeighbour;
			*pyNeighbour = yNeighbour;

//			Logger::debug("<<< MonteCarloIterator::getTilePair()");
			return true;
		}
	}

//	Logger::debug("<<< MonteCarloIterator::getTilePair()");
	return false;
}


void MonteCarloIterator::updateCount() {

	uint64 newUpdatesCount = _world._boundingBoxWidth * _world._boundingBoxHeight;

	if (_updatesCount != 0) {
		_updatesLeft = newUpdatesCount * _updatesLeft / _updatesCount;
	} else {
		_updatesLeft = newUpdatesCount;
	}
	_updatesCount = newUpdatesCount;

//	Logger::debug(QString("*** iterator new update left  : %1").arg(_updatesLeft));
//	Logger::debug(QString("*** iterator new update count : %1").arg(_updatesCount));
}

